home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Night Owl 6
/
Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso
/
039a
/
cport1.zip
/
COMDEMO.C
next >
Wrap
Text File
|
1991-06-03
|
21KB
|
872 lines
/*
** COMDEMO.C
**
** Serial communications demo program for the Cport communications library.
** Compiled and linked with Turbo C v2.01
**
** Copyright (c) 1991 Bri Productions
**
*/
#include "cport.h"
#include <conio.h>
#include <stdlib.h>
#include <dos.h>
#include <bios.h>
#include <ctype.h>
#include <stdio.h>
/*
**-------------------------------------
**
** Queue sizes and thresholds
**
**-------------------------------------
*/
#define TXQ 4096
#define RCVQ 4096
#define THRESH (RCVQ * 3 / 4)
/*
**-------------------------------------
**
** numbers of parameters
**
**-------------------------------------
*/
#define NUM_COM 4
#define NUM_BAUD 6
#define NUM_MODE 2
#define NUM_HND 4
/*
**-------------------------------------
**
** scan codes
**
**-------------------------------------
*/
#define A 0x1E00
#define B 0x3000
#define C 0x2E00
#define D 0x2000
#define E 0x1200
#define F 0x2100
#define G 0x2200
#define H 0x2300
#define I 0x1700
#define M 0x3200
#define N 0x3100
#define O 0x1800
#define P 0x1900
#define S 0x1F00
#define W 0x1100
#define X 0x2D00
#define ESC 0x1b
/*
**-------------------------------------
**
** text attributes
**
**-------------------------------------
*/
#define NORM 0x07
#define BOLD 0x08
#define FAINT 0xF7
#ifndef BLINK
#define BLINK 0x80
#endif
#define REVRS 0x77
/*
**-------------------------------------
**
** parameter constants
**
**-------------------------------------
*/
unsigned com[] = { COM1, COM2, COM3, COM4 };
int baud[] = { B19200, B9600, B4800, B2400, B1200, B300 };
byte mode[] = { W8|S1|NONE, W7|S1|EVEN };
/*
**-------------------------------------
**
** parameter indexes
**
**-------------------------------------
*/
struct indx{
byte com;
byte baud;
byte mode;
byte ansi;
byte hndshk;
byte lf;
byte echo;
}indx = { 0, 4, 0, 1, 0, 0, 0 };
/*
**-------------------------------------
**
** parameter messages
**
**-------------------------------------
*/
struct{
char *com [NUM_COM ];
char *baud [NUM_BAUD];
char *mode [NUM_MODE];
char *ansi [2];
char *hndshk[NUM_HND];
char *lf [2];
}msg={
{ "COM1", "COM2", "COM3", "COM4" },
{ "19200", "9600", "4800", "2400", "1200", "300"},
{ "8-1-N", "7-1-E" },
{ "TTY", "ANSI" },
{ "NONE", "SOFT", "HARD", "BOTH" },
{ " ", "LF" }
};
/*
**-------------------------------------
**
** screen coordinates
**
**-------------------------------------
*/
int x = 1; /* cursor location */
int y = 1;
byte attrib = NORM; /* present text attribute */
#define ERR_X 41 /* error message x coordinate */
#define STAT_X 60 /* status message x coordinate */
/*
**-------------------------------------
**
** function prototypes
**
**-------------------------------------
*/
void Init (void);
void Uninit (void);
void NewParam (void);
void Ansi (void);
void CheckError (void);
void CheckStatus (void);
void put_ch (char c);
/*
**-------------------------------------
**
** main()
**
**-------------------------------------
*/
void main(void)
{
struct C_param param;
char c;
unsigned key;
/* initialize */
Init();
while(1)
{
/* Poll the keyboard buffer for available keystrokes. */
/* Meanwhile, the receive queue is checked for available */
/* characters, check for errors and check the modem status */
while(!bioskey(1))
{
/* If a character(s) is available in the receive queue, */
/* fetch it. If it is and escape character, it must be */
/* check to see if it is the start of an ansi sequence. */
/* Otherwise the cursor position is updated, and the */
/* character is printed. */
if(ComLenRx())
{
c = ComGetc();
if(c == ESC && indx.ansi)
{
Ansi();
gotoxy(x, y);
continue;
}
put_ch(c);
}
/* Check for errors and changes in the modem status */
CheckError();
CheckStatus();
}
/* When a key is pressed, the key is fetched, and the */
/* keyboard flags are checked to see if the alt key was */
/* also pressed. If the alt key was pressed, we must */
/* check if the key is a valid command, and if so */
/* process it accordingly */
key = bioskey(0);
if(!(key & 0x00ff))
{
switch(key)
{
/* exit */
case X:
Uninit();
/* Next com port */
case C:
ComParam(¶m);
do
{
indx.com++;
indx.com %= NUM_COM;
param.com = com[indx.com];
}while(ComOpenS(¶m));
NewParam();
break;
/* Next baud rate */
case B:
indx.baud++;
indx.baud %= NUM_BAUD;
ComBaud(baud[indx.baud]);
NewParam();
break;
/* Next toggle mode */
case M:
indx.mode ^= 1;
ComMode(mode[indx.mode]);
NewParam();
break;
case A:
indx.ansi ^= 1;
NewParam();
break;
/* Next handshake scheme */
case H:
indx.hndshk++;
indx.hndshk %= NUM_HND;
ComHandshake(indx.hndshk, THRESH);
NewParam();
break;
/* Echo */
case E:
indx.echo ^= 1;
break;
/* Toggle LF append */
case N:
indx.lf ^= 1;
NewParam();
break;
/* Initialize hayes modem */
case I:
ComPuts("ATZ\r\n");
break;
/* Hayes modem dial command */
case D:
ComPuts("ATDT");
break;
/* Hayes modem hang up command */
case G:
ComPuts("~~~+++~~~ATH0\r\n");
break;
default:
continue;
}
}
/* If the key was not a command, put the character in the */
/* transmit queue. If the character is a carriage return, */
/* append a line feed to it just in case. */
else
{
ComPutc((char)key);
if(indx.echo)
put_ch((char)key);
CheckStatus();
CheckError();
}
}
}
/*
**-------------------------------------
**
** Modified putch()
**
**-------------------------------------
*/
void put_ch(char c)
{
gotoxy(x, y);
putch(c);
if(c == '\r' && indx.lf)
putch('\n');
if(c == '\b')
cputs(" \b");
x = wherex();
y = wherey();
}
/*
**-------------------------------------
**
** Initialize
**
**-------------------------------------
*/
void Init(void)
{
FILE *fp;
/* If an initialization file exists, load it. */
fp = fopen("comdemo.in1", "rb");
if(fp)
fread(&indx, sizeof(struct indx), 1, fp);
delay(0);
/* Set up the screen */
clrscr();
textattr(BLUE|(LIGHTGRAY<<4));
gotoxy(1,25);
cprintf(" %4s │%5s %s │ %-4s │ %-4s │ %2s │"
" no errors │ CTS= DSR= DCD= RI= ",
msg.com[indx.com],
msg.baud[indx.baud],
msg.mode[indx.mode],
msg.ansi[indx.ansi],
msg.hndshk[indx.hndshk],
msg.lf[indx.lf]);
/* Initialize the serial port to the default parameters, */
/* set the timeout and set the DTR and RTS lines. */
ComOpen(com[indx.com], baud[indx.baud], mode[indx.mode], RCVQ, TXQ);
/* restore the normal screen */
textattr(LIGHTGRAY);
window(1,1,80,24);
}
/*
**-------------------------------------
**
** terminate
**
**-------------------------------------
*/
void Uninit(void)
{
FILE *fp;
/* Store the present parameters in an .ini file so the program */
/* will remember next time it is executed. */
fp = fopen("comdemo.ini", "wb");
if(fp)
fwrite(&indx, sizeof(struct indx), 1, fp);
ComClose();
system("cls");
puts("\nCport version 1.10 Copyright (c) 1991 Bri Productions");
exit(0);
}
/*
**-------------------------------------
**
** new parameter
**
**-------------------------------------
*/
void NewParam(void)
{
/* Update the status line with the new parameters */
window(1,25, 80, 25);
textattr(BLUE|(LIGHTGRAY<<4));
cprintf(" %4s │%5s %s │ %-4s │ %-4s │ %s │",
msg.com[indx.com],
msg.baud[indx.baud],
msg.mode[indx.mode],
msg.ansi[indx.ansi],
msg.hndshk[indx.hndshk],
msg.lf[indx.lf]);
/* restore the normal screen */
textattr(attrib);
window(1,1,80,24);
gotoxy(x, y);
}
/*
**-------------------------------------
**
** ansi control sequence
**
**-------------------------------------
*/
void Ansi(void)
{
unsigned key;
char c;
char str[10];
int Pn[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int i=0,p=0;
static int oldx=1;
static int oldy=1;
/* While we are waiting for the next character, keep */
/* checking for keys. */
while((c = ComGetc()) == 0)
if(bioskey(1))
{
key = bioskey(0);
ComPutc((char)key);
}
/* If the next character is a '[' it is probably an ansi */
/* sequence. If the next character is not a '[', print the */
/* previous escape character followed by the new character. */
if(c != '[')
{
cprintf("\x1b%c",c);
return;
}
while(1)
{
/* Read the rest of the ansi sequence, while also checking */
/* for keys. */
while((c = ComGetc()) == 0)
{
key = bioskey(0);
ComPutc((char)key);
}
/* If the character is numeric, store it still it it's */
/* ascii form */
if(isdigit(c))
{
*(str+i++) = c;
continue;
}
/* When no more numeric characters are received, terminate */
/* the string and convert it to an integer, storing it in */
/* the parameter queue. */
*(str+i) = '\0';
i=0;
Pn[p++] = atoi(str);
/* Check for the ';' delimiter */
if(c == ';')
continue;
/* When no more numeric parameters are received, the */
/* command should be next. Now we can actually process */
/* the command using the stores parameters */
else
{
switch(c)
{
/* (CUP) set cursor position */
case 'H':
case 'F':
y = Pn[0] ? Pn[0] : 1;
x = Pn[1] ? Pn[1] : 1;
return;
/* (CUU) cursor up */
case 'A':
y -= Pn[0];
if(y < 1)
y = 1;
return;
/* (CUD) cursor down */
case 'B':
y += Pn[0];
if(y > 24)
y = 24;
return;
/* (CUF) cursor forward */
case 'C':
x += Pn[0];
if(x >80)
x = 80;
return;
/* (CUB) cursor backward */
case 'D':
x -= Pn[0];
if(x < 1)
x = 1;
return;
/* (SCP) save cursor position */
case 's':
oldx = x;
oldy = y;
return;
/* (RCP) restore cursor position */
case 'u':
x = oldx;
y = oldy;
return;
/* clear screen */
case 'J':
if(Pn[0] == 2)
{
clrscr();
x=1;
y=1;
}
else
{
window(1,wherey(),80,24);
clrscr();
window(1,1,80,24);
gotoxy(x, y);
}
return;
/* (EL) erase line */
case 'K':
clreol();
return;
/* An attribute command is more elaborate than the */
/* others because it may have many numeric parameters */
case 'm':
for(i=0; i<p; i++)
{
/* values from 30 to 37 define the foreground color */
if(Pn[i] >= 30 && Pn[i] <= 37)
{
attrib &= 0xf8;
attrib |= (Pn[i] - 30);
}
/* values from 40 to 47 define the background color */
if(Pn[i] >= 40 && Pn[i] <= 47)
{
attrib &= 0x8f;
attrib |= ((Pn[i] - 40) << 4);
}
/* values from 0 to 7 define the other attributes */
if(Pn[i] >= 0 && Pn[i] <= 7)
switch(Pn[i])
{
case 0:
attrib = NORM;
break;
case 1:
attrib |= BOLD;
break;
case 2:
attrib &= FAINT;
break;
case 5:
case 6:
attrib |= BLINK;
break;
case 7:
attrib ^= REVRS;
break;
default:
attrib = NORM;
}
}
/* The red and blue bits in the ansi standard are */
/* reversed relative to the IBM. Therefore, before we */
/* set the new attributes, if these bits are in */
/* opposite states toggled. This must be done for */
/* both the foreground and background. */
if((attrib & 0x05) == 0x04 || (attrib & 0x05) == 0x01)
attrib ^= 0x05;
if((attrib & 0x50) == 0x40 || (attrib & 0x50) == 0x10)
attrib ^= 0x50;
textattr(attrib);
default:
return;
}
}
}
}
/*
**-------------------------------------
**
** check for errors
**
**-------------------------------------
*/
void CheckError(void)
{
unsigned comerror;
static unsigned last_error = 0;
static int err_flg = 0;
char *errmsg[]= { { "no errors " },
{ "break detect " },
{ "frame error " },
{ "parity error " },
{ "overrun " },
{ "rx overflow " },
{ "tx overflow " }
};
comerror = ComError();
/* Check if the error code has changed since the last call. */
/* if it has not, there is no need to update the status line. */
/* If the error code has changed, the error conditions are */
/* checked in the order of their priority */
if(comerror != last_error)
{
last_error = comerror;
if(comerror & BREAK)
err_flg = 1;
else if(comerror & FRAMING)
err_flg = 2;
else if(comerror & PARITY)
err_flg = 3;
else if(comerror & OVERUN)
err_flg = 4;
else if(comerror & RXFULL)
err_flg = 5;
else if(comerror & TXFULL)
err_flg = 6;
else
err_flg = 0;
/* Update the status line with the new information */
window(1,25, 80, 25);
textattr(BLUE|(LIGHTGRAY<<4));
gotoxy(ERR_X,1);
cprintf(errmsg[err_flg]);
/* restore the normal screen */
textattr(attrib);
window(1,1,80,24);
gotoxy(x, y);
}
}
/*
**-------------------------------------
**
** check modem status
**
**-------------------------------------
*/
void CheckStatus(void)
{
byte status;
static byte last_status = 1;
int i;
status = ComStatus();
/* Check if the modem status has changed since the last call. */
/* if it has not, there is no need to update the status line. */
/* If the modem status has changed, each bit is checked for */
/* it's condition and printed on the status line */
if(status != last_status)
{
last_status = status;
window(1,25, 80, 25);
textattr(BLUE|(LIGHTGRAY<<4));
/* On each iteration, i = the x coordinate in the status */
/* line. The bits are checked for left to right. The */
/* statement !!(status & 0x10) resolves to 1 if the bit */
/* is set or 0 if the bit is clear. By adding 0x30 the */
/* 1 or 0 is converted to an ascii character */
for(i=STAT_X; i<STAT_X+6*4; i+=6)
{
gotoxy(i,1);
putch(!!(status & 0x10) + 0x30);
status >>= 1;
}
/* restore the normal screen */
textattr(attrib);
window(1,1,80,24);
gotoxy(x, y);
}
}